home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xmbase-grok-1.2 / sumwin.c < prev    next >
C/C++ Source or Header  |  1995-06-25  |  9KB  |  285 lines

  1. /*
  2.  * create and display a summary list.
  3.  *
  4.  *    destroy_summary_menu(card)    destroy summary list in form widget
  5.  *    create_summary_menu(card,wf,sh)    create summary list in form widget
  6.  *    scroll_summary(card)        scroll summary such that current row
  7.  *                    is highlighted and visible
  8.  *    make_summary_line(buf,card,row)    make string describing one card
  9.  */
  10.  
  11. #include "config.h"
  12. #include <X11/Xos.h>
  13. #include <stdlib.h>
  14. #include <assert.h>
  15. #include <Xm/Xm.h>
  16. #include <Xm/List.h>
  17. #include <Xm/LabelP.h>
  18. #include "grok.h"
  19. #include "form.h"
  20. #include "proto.h"
  21.  
  22. static void sum_callback(Widget, XtPointer, XmListCallbackStruct *);
  23.  
  24. extern Display        *display;    /* everybody uses the same server */
  25. extern GC        gc;        /* everybody uses this context */
  26. extern struct pref    pref;        /* global preferences */
  27. extern CARD         *curr_card;    /* card being displayed in main win, */
  28. extern Pixel        color[NCOLS];    /* colors: COL_* */
  29. extern XFontStruct    *font[NFONTS];    /* fonts: FONT_* */
  30. extern XmFontList    fontlist[NFONTS];
  31.  
  32.  
  33. /*
  34.  */
  35.  
  36. void destroy_summary_menu(
  37.     register CARD    *card)        /* card to destroy */
  38. {
  39.     if (card->wsummary) {
  40.         XtDestroyWidget(card->wsummary);
  41.         card->wsummary = 0;
  42.     }
  43. }
  44.  
  45.  
  46. /*
  47.  * create a summary in a list widget, based on the card struct. Some query
  48.  * must have been done earlier, so that card->query is defined. Install the
  49.  * summary in form widget wform.
  50.  */
  51.  
  52. void create_summary_menu(
  53.     CARD        *card,        /* card with query results */
  54.     Widget        wform,        /* form widget to install into */
  55.     Widget        shell)        /* enclosing shell */
  56. {
  57.     CARD        dummy;        /* if no card yet, use empty card */
  58.     char        buf[1024];    /* summary line buffer */
  59.     XmStringTable    list;        /* string list for summary widget */
  60.     int        nlines;        /* # of lines, at least pref.sumlines*/
  61.     Arg        args[15];
  62.     int        n;
  63.  
  64.     if (!display)
  65.         return;
  66.     print_info_line();
  67.     if (!card)
  68.         mybzero((void *)(card = &dummy), sizeof(dummy));
  69.     if (card->wheader)
  70.         XtDestroyWidget(card->wsummary);
  71.     if (card->wsummary)
  72.         XtDestroyWidget(card->wsummary);
  73.     card->wsummary  = 0;
  74.     card->wsumshell = shell;
  75.  
  76.     nlines = card->nquery < pref.sumlines ? pref.sumlines : card->nquery;
  77.     list = (XmStringTable)XtMalloc(nlines * sizeof(XmString *));
  78.     for (n=0; n < card->nquery; n++) {
  79.         make_summary_line(buf, card, card->query[n]);
  80.         list[n] = XmStringCreateSimple(buf);
  81.     }
  82.     while (n < nlines)
  83.         list[n++] = XmStringCreateSimple(" ");
  84.     nlines = n;
  85.     make_summary_line(buf, card, -1);
  86.     strcat(buf, "                                                       ");
  87.     XtUnmanageChild(wform);
  88.  
  89.     n = 0;
  90.     XtSetArg(args[n], XmNtopAttachment,    XmATTACH_FORM);        n++;
  91.     XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  92.     XtSetArg(args[n], XmNleftOffset,    3);            n++;
  93.     XtSetArg(args[n], XmNfontList,        fontlist[FONT_COURIER]);n++;
  94.     card->wheader = XtCreateWidget(buf, xmLabelWidgetClass,
  95.             wform, args, n);
  96.     n = 0;
  97.     XtSetArg(args[n], XmNtopAttachment,    XmATTACH_WIDGET);    n++;
  98.     XtSetArg(args[n], XmNtopWidget,        card->wheader);        n++;
  99.     XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  100.     XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  101.     XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  102.     XtSetArg(args[n], XmNselectionPolicy,    XmBROWSE_SELECT);    n++;
  103.     XtSetArg(args[n], XmNvisibleItemCount,    pref.sumlines);        n++;
  104.     XtSetArg(args[n], XmNitemCount,        nlines);        n++;
  105.     XtSetArg(args[n], XmNitems,        list);            n++;
  106.     XtSetArg(args[n], XmNfontList,        fontlist[FONT_COURIER]);n++;
  107.     XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmSTATIC);        n++;
  108.     card->wsummary = XmCreateScrolledList(wform, "sumlist",
  109.             args, n);
  110.     XtAddCallback(card->wsummary, XmNbrowseSelectionCallback,
  111.                 (XtCallbackProc)sum_callback, (XtPointer)0);
  112.     XmListSelectPos(card->wsummary, 1, False);
  113.     XtManageChild(card->wheader);
  114.     XtManageChild(card->wsummary);
  115.     XtManageChild(wform);
  116.  
  117.     for (n=0; n < nlines; n++)
  118.         XmStringFree(list[n]);
  119.     XtFree((char *)list);
  120. }
  121.  
  122.  
  123. /*
  124.  * user pressed on a line. Read back changes to the old card displayed, if
  125.  * any, and display the new one.
  126.  */
  127.  
  128. /*ARGSUSED*/
  129. static void sum_callback(
  130.     Widget            widget,
  131.     XtPointer        item,
  132.     XmListCallbackStruct    *data)
  133. {
  134.     register CARD        *card = curr_card;
  135.  
  136.     card_readback_texts(card, -1);
  137.     if (card && data->item_position-1 < card->nquery) {
  138.         card->qcurr = data->item_position-1;
  139.         card->row   = card->query[card->qcurr];
  140.         fillout_card(card, FALSE);
  141.     }
  142. }
  143.  
  144.  
  145. /*
  146.  * compose one line for the summary from a data row. Before starting, the
  147.  * items must be sorted by database column. Choice items are a special case
  148.  * because all choice items with identical names share one column. Only if
  149.  * the last choice item with a certain name doesn't match, print blanks.
  150.  * if row < 0, create a header line.
  151.  */
  152.  
  153. static int compare(
  154.     register MYCONST void *u,
  155.     register MYCONST void *v)
  156. {
  157.     return((*(ITEM **)u)->sumcol - (*(ITEM **)v)->sumcol);
  158. }
  159.  
  160.  
  161. void make_summary_line(
  162.     char        *buf,        /* text buffer for result line */
  163.     CARD        *card,        /* card with query results */
  164.     int        row)        /* database row */
  165. {
  166.     static int    nsorted;    /* size of <sorted> array */
  167.     static ITEM    **sorted;    /* sorted item pointer list */
  168.     char        *data;        /* data string from the database */
  169.     char        databuf[200];    /* buffer for data with ':' stripped */
  170.     ITEM        *item;        /* contains info about formatting */
  171.     int        x = 0;        /* index to next free char in buf */
  172.     int        i;        /* item counter */
  173.     int        j;        /* char copy counter */
  174.  
  175.     *buf = 0;
  176.     if (!card || !card->dbase || !card->form || row >= card->dbase->nrows)
  177.         return;
  178.     if (card->form->nitems > nsorted) {
  179.         nsorted = card->form->nitems + 3;
  180.         if (sorted)
  181.             free((void *)sorted);
  182.         if (!(sorted = (ITEM **)malloc(nsorted * sizeof(ITEM *)))) {
  183.             nsorted = 0;
  184.             return;
  185.         }
  186.     }
  187.     for (i=0; i < card->form->nitems; i++)
  188.         sorted[i] = card->form->items[i];
  189.     qsort((void *)sorted, card->form->nitems, sizeof(ITEM *), compare);
  190.  
  191.     for (i=0; i < card->form->nitems; i++) {
  192.         item = sorted[i];
  193.         if (!IN_DBASE(item->type) || item->sumwidth < 1)
  194.             continue;
  195.         data = row<0 ? item->type==IT_CHOICE ? item->name : item->label
  196.                  : dbase_get(card->dbase, row, item->column);
  197.  
  198.         if (row < 0 && data && data[j = strlen(data)-1] == ':') {
  199.             strncpy(databuf, data, sizeof(databuf));
  200.             databuf[j] = 0;
  201.             databuf[sizeof(databuf)-1] = 0;
  202.             data = databuf;
  203.         }
  204.         if (item->type == IT_CHOICE && row >= 0 &&
  205.             (!data || !item->flagcode || strcmp(data,item->flagcode))){
  206.             for (j=i+1; j < card->form->nitems; j++)
  207.                 if (!strcmp(item->name, sorted[j]->name))
  208.                     break;
  209.             if (j < card->form->nitems)
  210.                 continue;
  211.             data = 0;
  212.         }
  213.         if ((item->type == IT_CHOICE || item->type == IT_FLAG)
  214.                 && item->flagtext && item->flagcode && data
  215.                 && !strcmp(data, item->flagcode))
  216.             data = item->flagtext;
  217.         if (item->type == IT_TIME && row >= 0)
  218.             data = format_time_data(data, item->timefmt);
  219.         if (data)
  220.             strncpy(buf+x, data, 80);
  221.         buf[x + item->sumwidth] = 0;
  222.         for (j=x; buf[j]; j++)
  223.             if (buf[j] == '\n')
  224.                 buf[j--] = 0;
  225.         x += j = strlen(buf+x);
  226.         for (j; j < item->sumwidth && j < 80; j++)
  227.             buf[x++] = ' ';
  228.         buf[x++] = ' ';
  229.         buf[x++] = ' ';
  230.         buf[x]   = 0;
  231.         while (++i < card->form->nitems-1 &&
  232.                     item->sumcol == sorted[i]->sumcol);
  233.         i--;
  234.     }
  235.     if (x == 0)
  236.         sprintf(buf, row < 0 ? "" : "card %d", row);
  237. }
  238.  
  239.  
  240. /*
  241.  * scroll summary such that the current row is visible. This is used to jump
  242.  * to the first or last row, and to make sure the current card is highlighted
  243.  * after the user pressed the next or prev arrows below the card.
  244.  */
  245.  
  246. void scroll_summary(
  247.     CARD        *card)        /* which card's summary */
  248. {
  249.     Arg        args[2];
  250.     int        top=0, nvis=0;
  251.  
  252.     if (card->wsummary && card->qcurr < card->nquery) {
  253.         XtSetArg(args[0], XmNtopItemPosition,  &top);
  254.         XtSetArg(args[1], XmNvisibleItemCount, &nvis);
  255.         XtGetValues(card->wsummary, args, 2);
  256.         if (card->qcurr+1 < top)
  257.             XmListSetPos(card->wsummary, card->qcurr+1);
  258.         else if (card->qcurr+1 >= top + nvis)
  259.             XmListSetBottomPos(card->wsummary, card->qcurr+1);
  260.         XmListSelectPos(card->wsummary, card->qcurr+1, False);
  261.     }
  262. }
  263.  
  264.  
  265. /*
  266.  * replace a line in the list. This is done whenever card_readback_texts()
  267.  * reads text strings from the card menu back into the database. This
  268.  * routine updates the summary window accordingly.
  269.  */
  270.  
  271. void replace_summary_line(
  272.     CARD        *card,        /* card with query results */
  273.     int        row)        /* database row that has changed */
  274. {
  275.     char        buf[1024];    /* summary line buffer */
  276.     XmString    list;        /* string that replaces summary line */
  277.  
  278.     if (!card || !card->dbase || !card->form || row >= card->dbase->nrows)
  279.         return;
  280.     make_summary_line(buf, card, row);
  281.     list = XmStringCreateSimple(buf);
  282.     XmListReplaceItemsPos(card->wsummary, &list, 1, card->qcurr+1);
  283.     XmStringFree(list);
  284. }
  285.